home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / utility3 / wincap.zip / FILE.C < prev    next >
C/C++ Source or Header  |  1991-11-05  |  9KB  |  329 lines

  1. /*
  2.  *  file.c
  3.  *
  4.  *  Source file for Device-Independent Bitmap (DIB) API.  Provides
  5.  *  the following functions:
  6.  *
  7.  *  SaveDIB()           - Saves the specified dib in a file
  8.  *  LoadDIB()           - Loads a DIB from a file
  9.  *  DestroyDIB()        - Deletes DIB when finished using it
  10.  *
  11.  * Development Team: Mark Bader
  12.  *                   Patrick Schreiber
  13.  *                   Garrett McAuliffe
  14.  *                   Eric Flo
  15.  *                   Tony Claflin
  16.  *
  17.  * Written by Microsoft Product Support Services, Developer Support.
  18.  * Copyright (c) 1991 Microsoft Corporation. All rights reserved.
  19.  */
  20. #include <windows.h>
  21. #include <string.h>
  22. #include <stdio.h>
  23. #include <math.h>
  24. #include <io.h>
  25. #include <direct.h>
  26. #include <stdlib.h>
  27. #include "errors.h"
  28. #include "dibutil.h"
  29. #include "dibapi.h"
  30.  
  31. /*
  32.  * Dib Header Marker - used in writing DIBs to files
  33.  */
  34. #define DIB_HEADER_MARKER   ((WORD) ('M' << 8) | 'B')
  35.  
  36.  
  37. /*********************************************************************
  38.  *
  39.  * Local Function Prototypes
  40.  *
  41.  *********************************************************************/
  42.  
  43.  
  44. HANDLE ReadDIBFile(int);
  45. BOOL MyRead(int, LPSTR, DWORD);
  46. BOOL SaveDIBFile(void);
  47. BOOL WriteDIB(LPSTR, HANDLE);
  48. DWORD PASCAL MyWrite(int, VOID FAR *, DWORD);
  49.  
  50. /*************************************************************************
  51.  *
  52.  * LoadDIB()
  53.  *
  54.  * Loads the specified DIB from a file, allocates memory for it,
  55.  * and reads the disk file into the memory.
  56.  *
  57.  * Parameters:
  58.  *
  59.  * LPSTR lpFileName - specifies the file to load a DIB from
  60.  *
  61.  * Returns: A handle to a DIB, or NULL if unsuccessful.
  62.  *
  63.  *************************************************************************/
  64.  
  65.  
  66. HDIB LoadDIB(LPSTR lpFileName)
  67. {
  68.    HDIB hDIB;
  69.    int hFile;
  70.    OFSTRUCT ofs;
  71.  
  72.    /*
  73.     * Set the cursor to a hourglass, in case the loading operation
  74.     * takes more than a sec, the user will know what's going on.
  75.     */
  76.  
  77.    SetCursor(LoadCursor(NULL, IDC_WAIT));
  78.    if ((hFile = OpenFile(lpFileName, &ofs, OF_READ)) != -1)
  79.    {
  80.       hDIB = ReadDIBFile(hFile);
  81.       _lclose(hFile);
  82.       SetCursor(LoadCursor(NULL, IDC_ARROW));
  83.       return hDIB;
  84.    }
  85.    else
  86.    {
  87.       DIBError(ERR_FILENOTFOUND);
  88.       SetCursor(LoadCursor(NULL, IDC_ARROW));
  89.       return NULL;
  90.    }
  91. }
  92.  
  93.  
  94. /*************************************************************************
  95.  *
  96.  * SaveDIB()
  97.  *
  98.  * Saves the specified DIB into the specified file name on disk.  No
  99.  * error checking is done, so if the file already exists, it will be
  100.  * written over.
  101.  *
  102.  * Parameters:
  103.  *
  104.  * HDIB hDib - Handle to the dib to save
  105.  *
  106.  * LPSTR lpFileName - pointer to full pathname to save DIB under
  107.  *
  108.  * Return value: 0 if successful, or one of:
  109.  *        ERR_INVALIDHANDLE
  110.  *        ERR_OPEN
  111.  *        ERR_LOCK
  112.  *
  113.  *************************************************************************/
  114.  
  115.  
  116. WORD SaveDIB(HDIB hDib, LPSTR lpFileName)
  117. {
  118.    BITMAPFILEHEADER bmfHdr; // Header for Bitmap file
  119.    LPBITMAPINFOHEADER lpBI;   // Pointer to DIB info structure
  120.    int fh;     // file handle for opened file
  121.    OFSTRUCT of;     // OpenFile structure
  122.  
  123.    if (!hDib)
  124.       return ERR_INVALIDHANDLE;
  125.    fh = OpenFile(lpFileName, &of, OF_CREATE | OF_READWRITE);
  126.    if (fh == -1)
  127.       return ERR_OPEN;
  128.  
  129.    /*
  130.     * Get a pointer to the DIB memory, the first of which contains
  131.     * a BITMAPINFO structure
  132.     */
  133.    lpBI = (LPBITMAPINFOHEADER)GlobalLock(hDib);
  134.    if (!lpBI)
  135.       return ERR_LOCK;
  136.  
  137.    /*
  138.     * Fill in the fields of the file header
  139.     */
  140.  
  141.    /* Fill in file type (first 2 bytes must be "BM" for a bitmap) */
  142.    bmfHdr.bfType = DIB_HEADER_MARKER;  // "BM"
  143.  
  144.    /* Size is size of packed dib in memory plus size of file header */
  145.    bmfHdr.bfSize = GlobalSize(hDib) + sizeof(BITMAPFILEHEADER);
  146.    bmfHdr.bfReserved1 = 0;
  147.    bmfHdr.bfReserved2 = 0;
  148.  
  149.    /*
  150.     * Now, calculate the offset the actual bitmap bits will be in
  151.     * the file -- It's the Bitmap file header plus the DIB header,
  152.     * plus the size of the color table.
  153.     */
  154.    bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize +
  155.                       PaletteSize((LPSTR)lpBI);
  156.  
  157.    /* Write the file header */
  158.    _lwrite(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
  159.  
  160.    /*
  161.     * Write the DIB header and the bits -- use local version of
  162.     * MyWrite, so we can write more than 32767 bytes of data
  163.     */
  164.    MyWrite(fh, (LPSTR)lpBI, GlobalSize(hDib));
  165.    GlobalUnlock(hDib);
  166.    _lclose(fh);
  167.    return 0; // Success code
  168. }
  169.  
  170.  
  171. /*************************************************************************
  172.  *
  173.  * DestroyDIB ()
  174.  *
  175.  * Purpose:  Frees memory associated with a DIB
  176.  *
  177.  * Returns:  Nothing
  178.  *
  179.  *************************************************************************/
  180.  
  181.  
  182. WORD DestroyDIB(HDIB hDib)
  183. {
  184.    GlobalFree(hDib);
  185.    return 0;
  186. }
  187.  
  188.  
  189. //************************************************************************
  190. //
  191. // Auxiliary Functions which the above procedures use
  192. //
  193. //************************************************************************
  194.  
  195.  
  196. /*************************************************************************
  197.  
  198.   Function:  ReadDIBFile (int)
  199.  
  200.    Purpose:  Reads in the specified DIB file into a global chunk of
  201.              memory.
  202.  
  203.    Returns:  A handle to a dib (hDIB) if successful.
  204.              NULL if an error occurs.
  205.  
  206.   Comments:  BITMAPFILEHEADER is stripped off of the DIB.  Everything
  207.              from the end of the BITMAPFILEHEADER structure on is
  208.              returned in the global memory handle.
  209.  
  210. *************************************************************************/
  211.  
  212.  
  213. HANDLE ReadDIBFile(int hFile)
  214. {
  215.    BITMAPFILEHEADER bmfHeader;
  216.    DWORD dwBitsSize;
  217.    HANDLE hDIB;
  218.    LPSTR pDIB;
  219.  
  220.    /*
  221.     * get length of DIB in bytes for use when reading
  222.     */
  223.  
  224.    dwBitsSize = filelength(hFile);
  225.  
  226.    /*
  227.     * Go read the DIB file header and check if it's valid.
  228.     */
  229.    if ((_lread(hFile, (LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(
  230.        bmfHeader)) || (bmfHeader.bfType != DIB_HEADER_MARKER))
  231.    {
  232.       return NULL;
  233.    }
  234.    /*
  235.     * Allocate memory for DIB
  236.     */
  237.    hDIB = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
  238.    if (hDIB == 0)
  239.    {
  240.       return NULL;
  241.    }
  242.    pDIB = GlobalLock(hDIB);
  243.  
  244.    /*
  245.     * Go read the bits.
  246.     */
  247.    if (!MyRead(hFile, pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)))
  248.    {
  249.       GlobalUnlock(hDIB);
  250.       GlobalFree(hDIB);
  251.       return NULL;
  252.    }
  253.    GlobalUnlock(hDIB);
  254.    return hDIB;
  255. }
  256.  
  257. /*************************************************************************
  258.  
  259.   Function:  MyRead (int, LPSTR, DWORD)
  260.  
  261.    Purpose:  Routine to read files greater than 64K in size.
  262.  
  263.    Returns:  TRUE if successful.
  264.              FALSE if an error occurs.
  265.  
  266.   Comments:
  267.  
  268. *************************************************************************/
  269.  
  270.  
  271. BOOL MyRead(int hFile, LPSTR lpBuffer, DWORD dwSize)
  272. {
  273.    char huge *lpInBuf = (char huge *)lpBuffer;
  274.    int nBytes;
  275.  
  276.    /*
  277.     * Read in the data in 32767 byte chunks (or a smaller amount if it's
  278.     * the last chunk of data read)
  279.     */
  280.  
  281.    while (dwSize)
  282.    {
  283.       nBytes = (int)(dwSize > (DWORD)32767 ? 32767 : LOWORD (dwSize));
  284.       if (_lread(hFile, (LPSTR)lpInBuf, nBytes) != (WORD)nBytes)
  285.          return FALSE;
  286.       dwSize -= nBytes;
  287.       lpInBuf += nBytes;
  288.    }
  289.    return TRUE;
  290. }
  291.  
  292.  
  293. /****************************************************************************
  294.  
  295.  FUNCTION   : MyWrite(int fh, VOID FAR *pv, DWORD ul)
  296.  
  297.  PURPOSE    : Writes data in steps of 32k till all the data is written.
  298.               Normal _lwrite uses a WORD as 3rd parameter, so it is
  299.               limited to 32767 bytes, but this procedure is not.
  300.  
  301.  RETURNS    : 0 - If write did not proceed correctly.
  302.               number of bytes written otherwise.
  303.  
  304.  ****************************************************************************/
  305.  
  306.  
  307. DWORD PASCAL MyWrite(int iFileHandle, VOID FAR *lpBuffer, DWORD dwBytes)
  308. {
  309.    DWORD dwBytesTmp = dwBytes;       // Save # of bytes for return value
  310.    BYTE huge *hpBuffer = lpBuffer;   // make a huge pointer to the data
  311.  
  312.    /*
  313.     * Write out the data in 32767 byte chunks.
  314.     */
  315.  
  316.    while (dwBytes > 32767)
  317.    {
  318.       if (_lwrite(iFileHandle, (LPSTR)hpBuffer, (WORD)32767) != 32767)
  319.          return 0;
  320.       dwBytes -= 32767;
  321.       hpBuffer += 32767;
  322.    }
  323.  
  324.    /* Write out the last chunk (which is < 32767 bytes) */
  325.    if (_lwrite(iFileHandle, (LPSTR)hpBuffer, (WORD)dwBytes) != (WORD)dwBytes)
  326.       return 0;
  327.    return dwBytesTmp;
  328. }
  329.